////////////////////////////////////////////////////////////////////////////////
//
//  MICROSOFT CORPORATION
//  Copyright (c) Microsoft Corporation.
//  All Rights Reserved.
//
//  NOTICE: Microsoft Confidential. Intended for Internal Use Only.
//
////////////////////////////////////////////////////////////////////////////////

package com.msn.beet.logging
{

/**
 * Basic LogHandler handler for use with Log utility, outputs to flex
 * builder console and FlashTracer. Specify a new pattern layout with the
 * following tokens:
 *
 * <code>{message}, {logLevel}, {upTime}, {timeStamp}, {className},
 * {line}</code>
 *
 * <p>Default pattern:</p>
 * <code>{logLevel} - {className}, {line} - {message}</code>
 *
 */
public class TraceHandler implements ILogHandler
{
    include "../core/Version.as";

    public static const DEFAULT_FORMAT:String = "{logLevel} - {className}, " +
                                                "{line} - {message}";
    public static const MESSAGE:String = "{message}";
    public static const LOG_LEVEL:String = "{logLevel}";
    public static const UP_TIME:String = "{upTime}";
    public static const TIME_STAMP:String = "{timeStamp}";
    public static const CLASS_NAME:String = "{className}";
    public static const LINE_NUMBER:String = "{line}";

    /**
    * Default pattern layout:
    * {logLevel} - {className}, {line} - {message}
    */
    protected var _format:String = DEFAULT_FORMAT;

    /**
     * Creates TraceHandler, overrides default pattern layout with a new
     * pattern layout if specified.
     * @param messageLayout        Any string formatted combination of
     * {message}, {logLevel}, {upTime}, {timeStamp}, {className}, {line}
     */
    public function TraceHandler(format:String = null)
    {
        if (format != null)
        {
            _format = format;
        }
    }

    /** The current pattern layout.      */
    public function get format():String
    {
        return _format;
    }

    public function set format(value:String):void
    {
        _format = value;
    }

    /**
     * Passes message and messageLayout to hydrateLayout, traces returned
     * string.
     * @param message
     */
    public function notify(message:Message):void
    {
        // trace output to Flex console
        trace(hydrateLayout(_format, message))
    }

    public function hydrateLayout(messageLayout:String,
                                  message:Message):String
    {
        return messageLayout // replacers chained together below
            .replace(new RegExp(MESSAGE,"g"),     printContent(message.content))
            .replace(new RegExp(LOG_LEVEL,"g"),   message.logLevel.name)
            .replace(new RegExp(UP_TIME,"g"),     message.upTime)
            .replace(new RegExp(TIME_STAMP,"g"),  formatDate(message.timeStamp))
            .replace(new RegExp(CLASS_NAME,"g"),  message.className)
            .replace(new RegExp(LINE_NUMBER,"g"), message.line);
    }

    /**
     * Converts date object to HH:MM:SS.mmm string.
     * @param date
     * @return
     */
    public function formatDate(date:Date):String
    {
        // HACK: Refactor with proper date/string formatter utility
        return (// format hours with leading zero
                (date.getHours() < 10) ? "0" + date.getHours()
                                       : date.getHours()) + ":" +
                // format minutes with leading zero
                ((date.getMinutes() < 10) ? "0" + date.getMinutes()
                                          : date.getMinutes()) + ":" +
                // format seconds with leading zero
                ((date.getSeconds() < 10) ? "0" + date.getSeconds()
                                          : date.getSeconds()
                // add trailing milliseconds
                ) + "." + date.getMilliseconds();
    }

    /**
     * Prints the contents of an array, seperated by whitespace.
     * @param content
     * @return
     */
    public function printContent(content:Array /* of Object */):String
    {
        // TODO: Serialize complex objects in XML, JASON, or YAML.
        return content.join(" ");
    }

}

}
